package com.jibei.mendo.utils;

import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;

import com.cosofteck.gpiodemo.GpioControl;
import com.jibei.mendo.R;
import com.jibei.mendo.activity.SettingActivity;
import com.jibei.mendo.bean.ConfigInfoBean;
import com.jibei.mendo.bean.IgnitionInfoBean;
import com.jibei.mendo.event.Event;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lhl on 2019/9/13.
 */
public class SendCommandUtil {

    private SendCommandUtil() {
    }

    public static SendCommandUtil getInstance() {
        return SendCommandUtil.Holder.instance;
    }

    private static class Holder {
        private static final SendCommandUtil instance = new SendCommandUtil();
    }

    /**
     * 无返回值释放所有的命令
     */
    public void sendAllReleaseCommandWithNoRe() {
        ThreadPoolUtils.execute(() -> {
            try {

                SerialPortUtil.getInstance().sendCommandWithBackDelay("F0FF02E7FF", 100);


            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 发送释放所有的命令
     */
    public void sendAllReleaseCommand() {
        ThreadPoolUtils.execute(() -> {
            try {

                SerialPortUtil.getInstance().sendCommandWithBackDelay("F0FF02E7FF", 100);

                boolean isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                        "F0FF02E701",
                        "F0FF03E7C0F7", 100);
                int errorCount = 1;
                if (!isSendSuccess) {
                    Log.d("lhl", "释放所有的指令   发送失败次数>>>" + errorCount);
                    while (!isSendSuccess && errorCount < 2) {
                        isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                                "F0FF02E701",
                                "F0FF03E7C0F7", 100);
                        errorCount++;
                        Log.d("lhl", "释放所有的指令   发送失败次数>>>" + errorCount);
                        Thread.sleep(20);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 发送释放的命令
     */
    public void sendReleaseCommand(List<ConfigInfoBean> configInfoBeanList) {
        List<String> errorVidLists = new ArrayList<>();
        for (int i = 0; i < configInfoBeanList.size(); i++) {
            try {
                /*boolean isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                        "F0" + configInfoBeanList.get(i).getVid() + "02E701",
                        "F0" + configInfoBeanList.get(i).getVid() + "03E7C0F7", 100);
                int errorCount = 1;
                if (!isSendSuccess) {
                    while (!isSendSuccess && errorCount < 10) {
                        isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                                "F0" + configInfoBeanList.get(i).getVid() + "02E701",
                                "F0" + configInfoBeanList.get(i).getVid() + "03E7C0F7", 100);
                        errorCount++;
                        Log.d("lhl", "释放指令   发送失败次数>>>" + errorCount);
                        Thread.sleep(10);
                    }
                }*/
                String backCommandStr = SerialPortUtil.getInstance().sendCommandWithBack("F0" + configInfoBeanList.get(i).getVid() + "02E701", 100);
                Log.d("lhl", "单个释放命令   第1次发送>>>返回值为=" + backCommandStr);
                //多次去发送自检命令
                for (int j = 0; j < 9; j++) {
                    if (!isItemReleaseCommandSuccess(configInfoBeanList.get(i).getVid(), backCommandStr)) {
                        backCommandStr = SerialPortUtil.getInstance().sendCommandWithBack("F0" + configInfoBeanList.get(i).getVid() + "02E701", 100);
                        Log.d("lhl", "单个释放命令   第" + (j + 2) + "次发送>>>返回值为=" + backCommandStr);
                    }
                }
                if (!isItemReleaseCommandSuccess(configInfoBeanList.get(i).getVid(), backCommandStr)) {
                    errorVidLists.add(Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        EventBusUtil.getInstance().postEvent(new Event(Constant.Events.COMMAND_RELEASE_ERROR_LIST, errorVidLists.toString()));
        GpioControl.writeGpioValue(Constant.PG.PG4, 0);//ready 灯熄灭
        Log.e("lhl", "release_error_vid_list>>>" + errorVidLists.toString());
    }

    /**
     * 发送ready指令
     */
    public void sendReadyCommand(List<ConfigInfoBean> configInfoBeanList) {
        List<String> errorVidLists = new ArrayList<>();
        for (int i = 0; i < configInfoBeanList.size(); i++) {

            try {
                if (GpioControl.readGpioValue(Constant.PG.PG12) == 1 && GpioControl.readGpioValue(Constant.PG.PG13) == 1) {
                    Log.d("lhl", "hi you in ready cmd pause !");
                    break;
                }
                boolean isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                        "F0" + configInfoBeanList.get(i).getVid() + "02E601",
                        "F0" + configInfoBeanList.get(i).getVid() + "03E6C1F7", 100);
                int errorCount = 1;
                if (!isSendSuccess) {
                    while (!isSendSuccess && errorCount < 5) {
                        isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                                "F0" + configInfoBeanList.get(i).getVid() + "02E601",
                                "F0" + configInfoBeanList.get(i).getVid() + "03E6C1F7", 100);
                        errorCount++;
                        Log.d("lhl", "Ready指令   发送失败次数>>>" + errorCount);
                        Thread.sleep(100);
                    }
                }
                if (!isSendSuccess) {
                    errorVidLists.add(Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Log.d("lhl", "errorlist长度:" + errorVidLists.size());
        if (errorVidLists.size() == 0) {
            Log.d("lhl", "debug in fccxx:" + errorVidLists.size());
            GpioControl.writeGpioDirection(Constant.PG.PG4, 1);//设置点火LED为输出状态
            GpioControl.writeGpioValue(Constant.PG.PG4, 1);//点亮预备LED
        }
        EventBusUtil.getInstance().postEvent(new Event(Constant.Events.COMMAND_READY_ERROR_LIST, errorVidLists.toString()));
        Log.e("lhl", "ready_error_vid_list内容>>>" + errorVidLists.toString());
    }

    /**
     * 发送点火命令
     */
    int globle_index, recovery_index;
    //String last_recinfottyS3="";
    public void sendDianHuoCommand(List<IgnitionInfoBean> ignitionInfoBeanList) {
        if (recovery_index != ignitionInfoBeanList.size() - 1) {
            globle_index = recovery_index;
            Log.d("lhl", "got recovery_index value = " + globle_index);
        } else
            globle_index = 0;


        for (int i = globle_index; i < ignitionInfoBeanList.size(); i++) {

            //Log.d("ly","Contains:"+last_recinfottyS3.contains(TimeCodeSerial.getInstance().recinfottyS3));

            long difTime = 0;
            if ((GpioControl.readGpioValue(Constant.PG.PG12) == 1 && GpioControl.readGpioValue(Constant.PG.PG13) == 1 )
                    || (TimeCodeSerial.getInstance().recinfottyS3.contains("STOP")))
            {

                recovery_index = i;
                Log.d("lhl", "hi you in fire cmd pause ! index recovery = " + recovery_index);
                break;
            }
            if (i == 0) {
                difTime = TimeUtil.getInstance().timeToMillisecond(ignitionInfoBeanList.get(0).getTime());
            } else {
                difTime = TimeUtil.getInstance().timeToMillisecond(ignitionInfoBeanList.get(i).getTime()) - TimeUtil.getInstance().timeToMillisecond(ignitionInfoBeanList.get(i - 1).getTime());//差值
            }
            //Log.i("lhl", "   时间差值为>>>" + difTime);
            SerialPortUtil.getInstance().sendCommandWithBack(delete0x(ignitionInfoBeanList.get(i).getCommand()), difTime);
            recovery_index = i;
            //last_recinfottyS3 = TimeCodeSerial.getInstance().recinfottyS3;
            //Log.d("ly","TimeCodeSerial Meg:"+last_recinfottyS3);
        }
    }

    /**
     * 发送自检命令，成功后再发送配置命令
     */
    public Map<String, List<String>> sendCheckCommand(List<ConfigInfoBean> configInfoBeanList) {
        Map<String, List<String>> stringListMap = new HashMap<>();
        List<String> errorCheckLists = new ArrayList<>();
        List<String> errorConfigLists = new ArrayList<>();

        for (int i = 0; i < configInfoBeanList.size(); i++) {
            List<String> stringList = null;
            List<String> deviceStringList = new ArrayList<>();
            if (GpioControl.readGpioValue(Constant.PG.PG12) == 1 && GpioControl.readGpioValue(Constant.PG.PG13) == 1) {
                Log.d("lhl", "hi you in check cmd pause !");
                break;
            }
            try {
                String backCommandStr = SerialPortUtil.getInstance().sendCommandWithBackDelay("F0" + configInfoBeanList.get(i).getVid() + "02E201", 90);
                Log.d("lhl", "自检命令   第1次发送>>>返回值为=" + backCommandStr);
                //多次去发送自检命令
                for (int j = 0; j < 2; j++) {
                    if (!isCheckCommandSuccess(configInfoBeanList.get(i).getVid(), backCommandStr)) {
                        backCommandStr = SerialPortUtil.getInstance().sendCommandWithBackDelay("F0" + configInfoBeanList.get(i).getVid() + "02E201", 100);
                        Log.d("lhl", "自检命令   第" + (j + 2) + "次发送>>>返回值为=" + backCommandStr);
                    }
                }
                if (isCheckCommandSuccess(configInfoBeanList.get(i).getVid(), backCommandStr)) {
                    stringList = handlerPortData(configInfoBeanList.get(i), backCommandStr);

                    //发送配置信息
                    /*boolean isSuccess = sendConfigCommand(configInfoBeanList.get(i));
                    if (!isSuccess) {
                        errorConfigLists.add(Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString());
                    }*/
                    if (configInfoBeanList.get(i) != null) {
                        String backConfigCommandStr = SerialPortUtil.getInstance().sendCommandWithBackDelay(configInfoBeanList.get(i).getConfigInfo(), 100);
                        Log.d("lhl", "配置命令   第1次发送>>>返回值为=" + backConfigCommandStr);
                        for (int n = 0; n < 2; n++) {
                            if (!isConfigCommandSuccess(configInfoBeanList.get(i).getVid(), backConfigCommandStr)) {
                                backConfigCommandStr = SerialPortUtil.getInstance().sendCommandWithBackDelay(configInfoBeanList.get(i).getConfigInfo(), 110);
                                Log.d("lhl", "配置命令   第" + (n + 2) + "次发送>>>返回值为=" + backConfigCommandStr);
                            }
                        }
                        if (isConfigCommandSuccess(configInfoBeanList.get(i).getVid(), backConfigCommandStr)) {
                            //配置成功后 搜寻有问题的点信息
                            for (int index = 0; index < stringList.size(); index++) {
                                if (stringList.get(index).equals("0")) {
                                    deviceStringList.add(index + 1 + "");
                                }
                            }
                            Log.d("lhl", "打印连接异常列表" + deviceStringList.toString());
                            if (deviceStringList.size() > 0) {
                                errorCheckLists.add("\n" + Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString() + Resources.getSystem().getString(R.string.error_point_list) + deviceStringList.toString() + "\r\n");
                            }
                        } else {
                            errorConfigLists.add("\n" + "ID" + Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString());
                        }

                    }
                } else {
                    stringList = allError();
                    errorCheckLists.add("\n" + "Offline DEV:" + Integer.valueOf(configInfoBeanList.get(i).getVid(), 16).toString());
                    //Log.d("lhl", "查询命令 ++++++"+"测试返回值为=" + backCommandStr+"stringList = "+stringList.toString());

                }
            } catch (Exception e) {
                stringList = allError();
                e.printStackTrace();
            }
            stringListMap.put(configInfoBeanList.get(i).getVid(), stringList);
        }
        String checkErrorList = errorCheckLists.toString();
        checkErrorList = checkErrorList.replace('[', ' ');
        checkErrorList = checkErrorList.replace(']', ' ');
        if (checkErrorList.length() <= 2) {
            checkErrorList = "ALL OK";

        }


        String configErrorList = errorConfigLists.toString();
        configErrorList = configErrorList.replace('[', ' ');
        configErrorList = configErrorList.replace(']', ' ');

        if (configErrorList.length() <= 2 && checkErrorList.equals("ALL OK")) {
            configErrorList = "ALL OK";
        }

        EventBusUtil.getInstance().postEvent(new Event(Constant.Events.COMMAND_CHECK_ERROR_LIST, checkErrorList));
        EventBusUtil.getInstance().postEvent(new Event(Constant.Events.COMMAND_CONFIG_ERROR_LIST, configErrorList));
        Log.e("lhl", "check_error_vid_list>>>" + errorCheckLists.toString());
        Log.e("lhl", "config_error_vid_list>>>" + errorConfigLists.toString());
        return stringListMap;
    }

    /**
     * 判断自检命令是否成功
     *
     * @param backCommandStr 自检命令
     * @param vidStr         从机id
     * @return 是否自检通过
     */
    private boolean isCheckCommandSuccess(String vidStr, String backCommandStr) {
        if (TextUtils.isEmpty(backCommandStr))
            return false;
        if (backCommandStr.length() == 18) {
            //                Log.i("lhl", "头部>>>" + backCommandStr.substring(0, 8) + ",尾部>>>" + backCommandStr.substring(16));
            String headerStr = backCommandStr.substring(0, 8);
            String footerStr = backCommandStr.substring(16);
            if (headerStr.equals("F0" + vidStr + "06E2") && footerStr.equals("F7")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断配置命令是否成功
     *
     * @param backCommandStr 配置命令
     * @param vidStr         从机id
     * @return 是否发送配置成功
     */
    private boolean isConfigCommandSuccess(String vidStr, String backCommandStr) {//"F0" + configInfoBean.getVid() + "03E9C1F7"
        if (TextUtils.isEmpty(backCommandStr))
            return false;
        if (backCommandStr.equals("F0" + vidStr + "03E9C1F7")) {
            return true;
        }
        return false;
    }

    /**
     * 判断单个释放命令是否成功
     *
     * @param backCommandStr 单个释放命令
     * @param vidStr         从机id
     * @return 是否释放成功
     */
    private boolean isItemReleaseCommandSuccess(String vidStr, String backCommandStr) {
        //F00318E7A00603312E302E374E53515A59302E302E3358000000F7
        if (TextUtils.isEmpty(backCommandStr))
            return false;
        if (backCommandStr.length() == 54) {
            //            Log.i("lhl", "头部>>>" + backCommandStr.substring(0, 8) + ",尾部>>>" + backCommandStr.substring(52));
            String headerStr = backCommandStr.substring(0, 8);
            String footerStr = backCommandStr.substring(52);
            if (headerStr.equals("F0" + vidStr + "18E7") && footerStr.equals("F7")) {
                return true;
            }
        }
        return false;
    }

    private List<String> allError() {
        List<String> stringList = new ArrayList<>();
        for (int j = 0; j < 32; j++) {
            stringList.add("0");
        }
        return stringList;
    }

    /**
     * 比较表格中的自检信息与返回的指令
     *
     * @param configInfoBean 表格中的配置信息
     * @param backCommandStr 返回自检的实际指令
     */
    private List<String> handlerPortData(ConfigInfoBean configInfoBean, String backCommandStr) {
        List<String> stringList = new ArrayList<>();

        String excelString = configInfoBean.getCheckInfo();

        char[] excelChars = excelString.toCharArray();
        char[] backCommandChars = hexToBinaryString(backCommandStr.substring(8, 16)) != null ? hexToBinaryString(backCommandStr.substring(8, 16)).toCharArray() : null;

        if (backCommandChars == null) {
            return null;
        }

        for (int i = 0; i < 32; i++) {
            char excelChar = excelChars[i];
            char commandChar = backCommandChars[i];
            // char 1 means Normal;char 0 means Abnormal-RED;char 2 means Empty
            if (excelChar == '1' && commandChar == '1') {
                stringList.add("1");//按照编排去插入 并且检测到有效插入,属于正常  标注蓝色
            }
            if (excelChar == '1' && commandChar == '0') {
                stringList.add("0");//编排此处应该有连接的,但是没有检测到 属于异常 红色标注
            }
            if (excelChar == '0' && commandChar == '1' || excelChar == '0' && commandChar == '0') {
                stringList.add("2");//编排此处应该是空连接  黄色标注
            }
        }
        Log.i("lhl", "表格中的自检信息>>>" + configInfoBean.getCheckInfo() + "   返回的指令>>>" + hexToBinaryString(backCommandStr.substring(8, 16)) + "   new data>>>" + stringList.toString());
        return stringList;
    }

    /**
     * 十六进制转二进制
     *
     * @param hexStr 十六进制
     * @return 结果
     */
    private String hexToBinaryString(String hex) {
        long i = Long.parseLong(hex, 16);
        //String bin = String.format("%032d", Long.parseLong(hex));
        String bin = Long.toBinaryString(i);
        Log.d("lhl", "bin 的数据是:" + bin);
        while (bin.length() != 32) {
            bin = "0" + bin;
            //Log.d("lhl", "bin_new:" + bin);
        }
        return bin;
    }

    /**
     * 去掉ox前缀
     *
     * @param commandStr 原命令
     * @return 结果
     */
    private String delete0x(String commandStr) {
        if (commandStr.startsWith("0x")) {
            return commandStr.substring(2);
        }
        return commandStr;
    }

    /**
     * 发送配置命令
     */
    private boolean sendConfigCommand(ConfigInfoBean configInfoBean) {
        if (configInfoBean != null) {
            try {
                boolean isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                        configInfoBean.getConfigInfo(),
                        "F0" + configInfoBean.getVid() + "03E9C1F7", 200);
                int errorCount = 1;
                if (!isSendSuccess) {
                    while (!isSendSuccess && errorCount < 3) {
                        isSendSuccess = SerialPortUtil.getInstance().sendCommand(
                                configInfoBean.getConfigInfo(),
                                "F0" + configInfoBean.getVid() + "03E9C1F7", 200);
                        errorCount++;
                        Log.d("lhl", "配置指令   发送失败次数>>>" + errorCount);
                        //                        Thread.sleep(20);
                    }
                } else {
                    return true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }
}
